package com.ruoyi.lottery.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.lottery.domain.*;
import com.ruoyi.lottery.mapper.LotActivityLotAwardMapper;
import com.ruoyi.lottery.mapper.LotActivityMapper;
import com.ruoyi.lottery.mapper.LotActivityUserMapper;
import com.ruoyi.lottery.mapper.LotTimesMapper;
import com.ruoyi.lottery.service.ILotActivityService;
import com.ruoyi.lottery.service.ILotActivityUserService;
import com.ruoyi.lottery.service.ILotAwardService;
import com.ruoyi.lottery.utils.AwardUtils;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 抽奖活动Service业务层处理
 *
 * @author shier
 * @date 2023-01-27
 */
@Service
public class LotActivityServiceImpl extends ServiceImpl<LotActivityMapper, LotActivity> implements ILotActivityService {

    @Autowired
    private ILotActivityUserService     lotActivityUserService;
    @Autowired
    private ISysUserService             sysUserService;
    @Autowired
    private ILotAwardService            lotAwardService;
    @Resource
    private LotTimesMapper              lotTimesMapper;
    @Resource
    private LotActivityLotAwardMapper   lotActivityLotAwardMapper;
    @Resource
    private LotActivityUserMapper       lotActivityUserMapper;

    /**
     * 查询抽奖活动列表
     *
     * @param lotActivity 抽奖活动
     * @return 抽奖活动
     */
    @Override
    public List<LotActivity> selectLotActivityList(LotActivity lotActivity) {

        // 得到活动集合
        List<LotActivity> lotActivities = getBaseMapper().selectLotActivityList(lotActivity);

        // 遍历集合
        for (LotActivity activity : lotActivities) {
            // 基于 活动ID 得到 中间表对象集合
            LambdaQueryWrapper<LotActivityUser> wrapper = Wrappers.lambdaQuery(LotActivityUser.class).eq(LotActivityUser::getActivityId, activity.getId());
            List<LotActivityUser> list = lotActivityUserService.list(wrapper);

            // 用户集合
            List<LotUser> lotUsers = new ArrayList<>();
            // 该活动发放的奖品金额
            BigDecimal money = new BigDecimal("0");

            for (LotActivityUser lotActivityUser : list) {

                // 奖品金额进行相加
                LotAward award = lotAwardService.getById(lotActivityUser.getAwardId());
                money = money.add(award.getMoney());

                LotUser lotUser = new LotUser();
                // 用户添加进用户集合
                SysUser sysUser = sysUserService.selectUserById(lotActivityUser.getUserId());
                BeanUtils.copyBeanProp(lotUser, sysUser);
                lotUser.setAward(award);
                lotUser.setAwardCreatTime(lotActivityUser.getCreatTime());

                lotUsers.add(lotUser);
            }

            // 该活动参与的用户集合
            activity.setUsers(lotUsers);
            // 该活动参与的人数
            activity.setUserCount(list.size());

            // 该活动发放奖品的金额
            activity.setMoney(money);
        }

        return lotActivities;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String lotteryAward(Long activityId) {

        // TODO: 假设当前用户的ID为1, 用户类型为老用户
        int currentUserParticipationLimit = 1;

        // 1: 基于 活动ID&用户ID 查询是否有抽奖次数
        LambdaQueryWrapper<LotTimes> lotTimesWrapper = Wrappers.lambdaQuery(LotTimes.class)
                .eq(LotTimes::getUserId, 1L)
                .eq(LotTimes::getActivityId, activityId);
        LotTimes lotTimes = lotTimesMapper.selectOne(lotTimesWrapper);

        if (lotTimes == null || lotTimes.getLotteryTimes() == 0) {
            return "你没有抽奖次数,请先去完成任务";
        }

        // 2: 查询该活动下的奖品ID集合
        LambdaQueryWrapper<LotActivityLotAward> actAwardWrapper = Wrappers.lambdaQuery(LotActivityLotAward.class).eq(LotActivityLotAward::getActivityId, activityId);
        List<LotActivityLotAward> lotActivityLotAwards = lotActivityLotAwardMapper.selectList(actAwardWrapper);
        List<Long> awardIds = lotActivityLotAwards.stream().map(LotActivityLotAward::getAwardId).collect(Collectors.toList());

        // 3: 根据 奖品ID集合 去查询 奖品对象
        List<LotAward> awards = lotAwardService.listByIds(awardIds);

        // 4: 去进行抽奖
        AwardUtils.setWeightLottery(awards);
        LotAward lotAward = AwardUtils.proceedLottery(awards); // 中奖对象

        // 5: 抽奖次数-1
        lotTimes.setLotteryTimes(lotTimes.getLotteryTimes() - 1);
        lotTimesMapper.updateById(lotTimes);

        // 6: 判断是否中间: 中奖对象 == null ===> 没有中奖
        if (lotAward == null) {
            return "谢谢惠顾";
        }

        // 7: 保存中奖信息
        LotActivityUser lotActivityUser = new LotActivityUser();
        lotActivityUser.setActivityId(activityId);
        lotActivityUser.setUserId(1L);
        lotActivityUser.setAwardId(lotAward.getId());
        lotActivityUser.setCreatTime(new Date());
        lotActivityUserMapper.insert(lotActivityUser);

        // 8: 返回提示消息
        return "恭喜你中奖了, 奖品为: " + lotAward.getName();
    }

    /**
     * 抽奖活动的新增功能
     *
     * @param entity    抽奖活动
     * @return          是否新增成功
     */
    @Override
    public boolean save(LotActivity entity) {

        // 创建时间为新增的时间
        entity.setCreateTime(new Date());

        // 创建时默认状态为正常
        entity.setStatus(LotActivity.ACTIVITY_STATUS_NORMAL);

        return super.save(entity);
    }

    /**
     * 抽奖活动的修改功能
     *
     * @param entity 抽奖活动对象
     * @return       是否修改成功
     */
    @Override
    public boolean updateById(LotActivity entity) {
        // 只有状态为正常才能修改
        if (entity.getStatus() == LotActivity.ACTIVITY_STATUS_NORMAL) {
            return super.updateById(entity);
        }
        return false;
    }
}
